﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using LowLevelGraphics.ColorSpaces;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Huerotation is used to rotate the hue value in this image,
    /// i.e. the whole image is recolored.
    /// </summary>
    public class HueRotation : BaseImageFilter
    {
        protected float m_fRotationFactor = 0.5f;

        /// <summary>
        /// Default constructor
        /// </summary>
        public HueRotation()
        {
        }

        /// <summary>
        /// primary constructor
        /// </summary>
        /// <param name="_fRotationFactor"></param>
        public HueRotation(float _fRotationFactor)
        {
            m_fRotationFactor = _fRotationFactor;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_hueRotation"></param>
        internal HueRotation(HueRotation _hueRotation)
        {
            this.m_fRotationFactor = _hueRotation.m_fRotationFactor;
        }

        /// <summary>
        /// Gets or sets the rotation factor
        /// This is the angle of rotation in the hue color circle
        /// </summary>
        public float RotationFactor
        {
            get { return m_fRotationFactor; }
            set { m_fRotationFactor = value; }
        }

        /// <summary>
        /// Executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;
            int width = bitmap.Width;
            int height = bitmap.Height;

            Rectangle rc = new Rectangle(0, 0, width, height);

            BitmapData dataSrc = bitmap.BitmapData; //source.LockBits(rc, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            int nBytesPerPixelCount = bitmap.BytesPerPixelCount;
            int offset = dataSrc.Stride - (width * nBytesPerPixelCount);

            Color color = Color.Transparent;

            //todo: implement bytes per pixel count

            unsafe
            {
                byte* bytesSrc = (byte*)(void*)dataSrc.Scan0;

                int y = 0;
                int x = 0;

                HSL hsl = null;
                for (y = 0; y < height; ++y)
                {
                    for (x = 0; x < width; ++x)
                    {
                        hsl = new HSL(Color.FromArgb(bytesSrc[2], bytesSrc[1], bytesSrc[0])); // Still BGR
                        hsl.H *= m_fRotationFactor;

                        color = hsl.ToColor();

                        bytesSrc[0] = color.B;
                        bytesSrc[1] = color.G;
                        bytesSrc[2] = color.R;
                        bytesSrc += nBytesPerPixelCount;
                    }

                    bytesSrc += offset;
                }

            }
            return _bitmap; //source.UnlockBits(dataSrc);
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new HueRotation(this);
        }
    }
}
